/* pfwUtilP.h - Private protocol framework util header file */

/* Copyright 1999 - 2005 Wind River Systems, Inc. */

/*
modification history
--------------------
01b,21jan05,vvv  SLL_xxx, DLL_xxx macros are now available in sllLib.h and
                 dllLib.h
01a,23feb00,sj   do not cast lvalue in DLL_GET and SLL_GET
*/

#ifndef __INCpfwUtilPh
#define __INCpfwUtilPh

#ifdef __cplusplus
extern "C" {
#endif


#include "sllLib.h"
#include "dllLib.h"

#if (!defined (_WRS_VXWORKS_MAJOR) || (_WRS_VXWORKS_MAJOR < 6))
/*******************************************************************************
*
* SLL_INIT - initialize singly linked list head
*
* Initialize the specified list to an empty list.
*/

#define SLL_INIT(list)                                                    \
    {                                                                     \
    ((SL_LIST *)(list))->head	 = NULL;                                  \
    ((SL_LIST *)(list))->tail	 = NULL;                                  \
    }

/*******************************************************************************
*
* SLL_PUT_AT_HEAD - add node to beginning of list
*
* This macro adds the specified node to the end of the specified list.
*
*/

#define  SLL_PUT_AT_HEAD(list, node)                                     \
    {                                                                    \
    if ((((SL_NODE *)(node))->next = ((SL_LIST *)(list))->head) == NULL) \
	{                                                                \
	((SL_LIST *)(list))->head = ((SL_NODE *)(node);                  \
	((SL_LIST *)(list))->tail = ((SL_NODE *)(node);                  \
    else                                                                 \
	((SL_LIST *)(list))->head = (node);                              \
    }

/*******************************************************************************
*
* SLL_PUT_AT_TAIL - add node to end of list
*
* This macro adds the specified node to the end of the specified singly
* linked list.
*
*/

#define  SLL_PUT_AT_TAIL(list, node)                                    \
    {                                                                   \
    ((SL_NODE *)(node))->next = NULL;                                    \
    if (((SL_LIST *)(list))->head == NULL)                              \
	{                                                               \
	((SL_LIST *)(list))->head = (SL_NODE *)(node);                  \
	((SL_LIST *)(list))->tail = (SL_NODE *)(node);                  \
	}                                                               \
    else                                                                \
	((SL_LIST *)(list))->tail->next = (SL_NODE *)(node);            \
	((SL_LIST *)(list))->tail = (SL_NODE *)(node);                  \
    }

/*******************************************************************************
*
* SLL_GET - get (delete and return) first node from list
*
* This macro gets the first node from the specified singly linked list,
* deletes the node from the list, and returns a pointer to the node gotten.
*
*/

#define SLL_GET(list, node)                                            \
    {                                                                  \
    if (((node) = (void *)((SL_LIST *)(list))->head) != NULL)       \
	((SL_LIST *)(list))->head = ((SL_NODE *)(node))->next;         \
    }

/*******************************************************************************
*
* SLL_REMOVE - remove specified node in list
*
* Remove the specified node in a singly linked list.
*/

#define SLL_REMOVE(list, deleteNode, previousNode)                           \
    {                                                                        \
    if (((SL_NODE *)(previousNode)) == NULL)                                 \
	{                                                                    \
	((SL_LIST *)(list))->head = ((SL_NODE *)(deleteNode))->next;         \
	if (((SL_LIST *)(list))->tail == ((SL_NODE *)(deleteNode)))          \
	    ((SL_LIST *)(list))->tail = NULL;                                \
	}                                                                    \
    else                                                                     \
	{                                                                    \
	((SL_NODE *)(previousNode))->next = ((SL_NODE *)(deleteNode))->next; \
	if (((SL_LIST *)(list))->tail == ((SL_NODE *)(deleteNode)))          \
	    ((SL_LIST *)(list))->tail = ((SL_NODE *)(previousNode));         \
	}                                                                    \
    }

/*******************************************************************************
*
* SLL_PREVIOUS - find and return previous node in list
*
* Find and return the previous node in a singly linked list.
*/

#define SLL_PREVIOUS(list, node, previousNode)                              \
    {                                                                       \
    SL_NODE *temp;                                                          \
    (SL_NODE *)(previousNode) = NULL;                                       \
    temp = ((SL_LIST *)(list))->head;                                       \
    if (temp != NULL) && (temp != (node))                                   \
	while (temp->next != NULL)                                          \
	    {                                                               \
	    if (temp->next == (node))                                       \
		{                                                           \
		(SL_NODE *)(previousNode) = temp;                           \
		break;                                                      \
		}                                                           \
	    temp = temp->next;                                              \
	    }                                                               \
    }
#endif /* !_WRS_VXWORKS_MAJOR */


/* typedefs */

typedef struct pfwQueueItem
    {
    SL_NODE node;
    } PFW_QUEUE_ITEM;

typedef struct pfwQueue
    {
    SL_LIST itemList;
    unsigned int count;
    unsigned int drops;
    } PFW_QUEUE;

#define PFW_QUEUE_INIT(queue)                  \
    {                                          \
    SLL_INIT ((queue));                        \
    ((PFW_QUEUE *)(queue))->count = 0;         \
    ((PFW_QUEUE *)(queue))->drops = 0;         \
    }

#define PFW_ENQUEUE(queue, item)               \
    {                                          \
    SLL_PUT_AT_TAIL ((queue), (item));         \
    ((PFW_QUEUE *)(queue))->count++;           \
    }

#define PFW_DEQUEUE(queue, item)               \
    {                                          \
    SLL_GET ((queue), (item));                 \
    if (((PFW_QUEUE *)(queue))->count > 0)     \
	((PFW_QUEUE *)(queue))->count--;       \
    }


#if (!defined (_WRS_VXWORKS_MAJOR) || (_WRS_VXWORKS_MAJOR < 6))
/*********************************************************************
*
* DLL_INIT - initialize doubly linked list descriptor
*
* Initialize the specified list to an empty list.
*/

#define DLL_INIT(list)                   \
    {                                    \
    ((DL_LIST *)(list))->head = NULL;                 \
    ((DL_LIST *)(list))->tail = NULL;                 \
    }

/************************************************************************
*
* DLL_INSERT - insert node in list after specified node
*
* This macro inserts the specified node in the specified list.
* The new node is placed following the specified 'previous' node in the list.
* If the specified previous node is NULL, the node is inserted at the head
* of the list.
*/

#define DLL_INSERT(list, previousNode, node)                       \
    {                                                              \
    DL_NODE *temp;                                                 \
    if ((previousNode) == NULL)                                    \
	{                                                          \
	temp = ((DL_LIST *)(list))->head;                          \
	((DL_LIST *)(list))->head = (DL_NODE *)(node);             \
	}                                                          \
    else                                                           \
	{                                                          \
        temp = ((DL_NODE *)(previousNode))->next;                  \
        ((DL_NODE *)(previousNode))->next = (DL_NODE *)(node);     \
	}                                                          \
    if (temp == NULL)                                              \
	((DL_LIST *)(list))->tail = (DL_NODE *)(node);             \
    else                                                           \
       temp->previous = (DL_NODE *)(node);                         \
    ((DL_NODE *)(node))->next = temp;                              \
    ((DL_NODE *)(node))->previous = (DL_NODE *)(previousNode);     \
    }

/************************************************************************
*
* DLL_ADD - add node to end of list
*
* This macro adds the specified node to the end of the specified list.
*/

#define DLL_ADD(list, node)                               \
    {                                                     \
    DL_NODE *listTail = (list)->tail;                     \
    DLL_INSERT ((list), listTail, (node));                \
    } 

/************************************************************************
*
* DLL_REMOVE - remove specified node in list
*
* Remove the specified node in the doubly linked list.
*/

#define DLL_REMOVE(list, node)                                                \
    {                                                                         \
    if (((DL_NODE *)(node))->previous == NULL)                                \
	((DL_LIST *)(list))->head = ((DL_NODE *)(node))->next;                \
    else                                                                      \
	((DL_NODE *)(node))->previous->next = ((DL_NODE *)(node))->next;      \
    if (((DL_NODE *)(node))->next == NULL)                                    \
	((DL_LIST *)(list))->tail = ((DL_NODE *)(node))->previous;            \
    else                                                                      \
	((DL_NODE *)(node))->next->previous = ((DL_NODE *)(node))->previous;  \
    }

/************************************************************************
*
* DLL_GET - get (delete and return) first node from list
*
* This macro gets the first node from the specified list, deletes the node
* from the list, and returns a pointer to the node gotten.
*
*/

#define DLL_GET(list, node)                                                 \
    {                                                                       \
    (node) = (void *)((DL_LIST *)(list))->head;                        \
    if ((node) != NULL)                                        \
	{                                                                   \
        ((DL_LIST *)(list))->head = ((DL_NODE *)(node))->next;              \
        if (((DL_NODE *)(node))->next == NULL)                              \
            ((DL_LIST *)(list))->tail = NULL;                               \
        else                                                                \
            ((DL_NODE *)(node))->next->previous = NULL;                     \
	}                                                                   \
    }
#endif /* !_WRS_VXWORKS_MAJOR */

#ifdef __cplusplus
}
#endif

#endif /* __INCpfwUtilPh */


